﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tunnel.Tools;
using Tunnel.Devices.DeviceEntity;
using Tunnel.Devices.DeviceEntity.Lamp;
using Tunnel.Entity;
using Tunnel.Tools.FcmsTools;
using System.IO;
using System.Net;
using System.Threading;
using Tunnel.Devices;
using System.ServiceModel;
using Tunnel.Plan;

namespace Tunnel
{
    /// <summary>
    /// 监控主界面窗体类
    /// </summary>
    public partial class MainForm : Form
    {
        /// <summary>
        /// 监控主窗体类构造方法
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 修改界面设备状态
        /// </summary>
        /// <param name="deviceID">设备ID</param>
        /// <param name="statusID">状态ID</param>
        /// <param name="statusDescription">设备状态描述</param>
        /// <param name="deviceType">设备类型ID</param>
        /// <param name="updateTime">更新时间</param>
        /// <returns>是否更新成功</returns>
        public bool ChangeDeviceStatus(string deviceID, string statusID, string statusDescription, string deviceType, string updateTime)
        {
            bool result = false;
            foreach (Control deviceControl in this.mainRoadPic.Controls.AsParallel())
            {
                if (deviceControl is DeviceBase device)
                {
                    if (device.DeviceId == deviceID)
                    {
                        device.DeviceStatusId = statusID;
                        device.StatusDescription = statusDescription;
                        device.UpdateTime = Convert.ToDateTime(updateTime);
                        result = true;
                    }
                    if (device.TypeId == deviceType && (device.DevicePos == "Light"))
                    {
                        device.DeviceStatusId = statusID;
                        device.StatusDescription = statusDescription;
                        device.UpdateTime = Convert.ToDateTime(updateTime);
                        result = true;
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 更新设备数值
        /// </summary>
        /// <param name="deviceID">设备ID</param>
        /// <param name="numType">设备数值类型</param>
        /// <param name="num1">数值1</param>
        /// <param name="num2">数值2</param>
        /// <param name="num3">数值3</param>
        /// <returns>是否更新成功</returns>
        public bool ChangeDeviceNum(string deviceID, string numType, int num1, int num2, int num3)
        {
            foreach (Control deviceControl in this.mainRoadPic.Controls.AsParallel())
            {
                if (deviceControl is DeviceBase device)
                {
                    if (device.DeviceId == deviceID)
                    {
                        switch (numType)
                        {
                            case "CO": (device as COVI).Co = num1; return true;
                            case "VI": (device as COVI).Vi = num1; return true;
                            case "WindSpeed":(device as Wind).WindSpeed = num1;return true;
                            case "WindDirect":(device as Wind).WindDirect = num1.ToString();return true;                            
                            default: return false;
                        }
                    }
                }
            }
            return false;
        }

        List<Fan> FANs = new List<Fan>();
        List<TS> TSs = new List<TS>();
        List<Lamp> Lamps = new List<Lamp>();
        List<FCMS> FCMSs = new List<FCMS>();
        List<COVI> COVIs = new List<COVI>();
        List<FiberPoint> FiberPoints = new List<FiberPoint>();
        List<FD> FDs = new List<FD>();
        List<Smoke> Smokes = new List<Smoke>();
        List<LC> LCs = new List<LC>();
        List<Wind> Winds = new List<Wind>();
        /// <summary>
        /// 设置窗体布局
        /// </summary>
        private void LayoutForm()
        {
            int screenWidth = SystemInformation.PrimaryMonitorSize.Width;
            int screenHeight = SystemInformation.PrimaryMonitorSize.Height;
            if ((screenWidth < 1920) || (screenHeight < 1080))
            {
                MessageBox.Show("本监控系统建议的显示器分辨率为1920*1080\r\n不使用本分辨率的显示器将无法正确显示监控画面的内容\r\n请将当前显示器分辨率设置为1920*1080\r\n如果当前显示器无法支持1920*1080分辨率，建议更换合适的显示设备", "屏幕分辨率不适用", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            this.titlePic.Location = new Point(0, 0);
            //this.titlePic.Size = new Size(this.Width, (int)(this.Height * 0.15));
            
            this.titlePic.Size = this.titlePic.Image.Size;
            this.timeLabel.Parent = titlePic;
            this.timeLabel.Text = "2099年12月31日 23:59:59";
            this.timeLabel.Location = new Point(this.titlePic.Width - this.timeLabel.Width - this.appExitPic.Width - this.minisizeForm.Width, 10);
            this.btTimePlan.Parent = titlePic;
            this.btPlan.Parent = titlePic;
            this.btAlarm.Parent = titlePic;
            this.btTimePlan.Location = new Point(this.Width - btTimePlan.Width, this.titlePic.Height - btTimePlan.Height - 3);
            this.btPlan.Location = new Point(this.Width - btTimePlan.Width-btPlan.Width, this.titlePic.Height - btPlan.Height - 3);
            this.btAlarm.Location = new Point(this.Width - btTimePlan.Width - btPlan.Width - btAlarm.Width, this.titlePic.Height - btAlarm.Height - 3);
            this.mainPanel.Location = new Point(0, this.titlePic.Height);
            this.mainPanel.Size = new Size(this.Width, this.mainRoadPic.Image.Height);

            this.mainRoadPic.Location = new Point(0, 0);
            this.mainRoadPic.Size = this.mainRoadPic.Image.Size;

            this.appExitPic.Parent = this.titlePic;
            this.minisizeForm.Parent = this.titlePic;
            this.appExitPic.Location = new Point(this.Width - this.appExitPic.Width, 0);
            this.minisizeForm.Location = new Point(this.titlePic.Width - this.appExitPic.Width - this.minisizeForm.Width, 0);
            this.appExitPic.Parent = this.titlePic;
            this.MessageLabel.Parent = titlePic;
            this.MessageLabel.Location = new Point(20, this.titlePic.Height - 33);
            DataDeal.ShowMessage("监控系统已启动");
        }
        /// <summary>
        /// 定义服务实例
        /// </summary>
        DataConnectionServices ReciveStateService;
        /// <summary>
        /// 服务承载实例
        /// </summary>
        ServiceHost ReciveStateServiceHost;
        /// <summary>
        /// 定时运行预案系统
        /// </summary>
        public TimeToRun timeToRun;

        private async void MainForm_Load(object sender, EventArgs e)
        {
            this.Text = Properties.Settings.Default.TunnelName + "监控系统";
            this.Size = new Size(1920, 1080);
            this.Location = new Point(0, 0);
            FanTimeControl.Inti();
            LayoutForm();
            await DeplyDevices();
            RefreshDeviceStatus();

            this.timerRefreshStatus.Interval = Properties.Settings.Default.RefreshTime * 1000;
            timerRefreshStatus.Start();

            ReciveStateService = new DataConnectionServices();
            ReciveStateServiceHost = new ServiceHost(ReciveStateService);

            try
            {
                ReciveStateServiceHost.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            timeToRun = new TimeToRun();
            timeToRun.StartTimer();
            ClockShow();
        }
        /// <summary>
        /// 显示时间
        /// </summary>
        private void ClockShow()
        {
            System.Timers.Timer clockTimer = new System.Timers.Timer();
            clockTimer.Elapsed += ShowTimeNow;
            clockTimer.Interval = 1000;
            clockTimer.Start();
        }        
        private void ShowTimeNow(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.timeLabel.Invoke(new EventHandler(delegate { this.timeLabel.Text = DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss"); }));
        }

        /// <summary>
        /// 部署设备
        /// </summary>
        /// <returns>可等待</returns>
        private async Task DeplyDevices()
        {
            FANs.Clear();
            TSs.Clear();
            Lamps.Clear();

            DBHelper dh = new DBHelper();
            DataTable dtAllDevices = await dh.GetTableAsync("SELECT   M_Device.DeviceID, M_Device.DeviceStatusID, M_Device.ShortName, M_Device.Name, M_Device.TypeID, M_Device.DevicePos, M_Device.PicX, M_Device.PicY, M_Device.Protocol, M_Device.Port, M_Device.Controllable,M_Device.UpdateTime, M_Device.UserID, M_Device.Road, M_Device.FactoryID, M_Device.Model, M_Device.Tunnel, M_DeviceType.Name AS Expr2, M_DeviceType.Controllable AS Expr3 FROM  M_Device LEFT OUTER JOIN M_DeviceType ON M_Device.TypeID = M_DeviceType.TypeID");

            if(dtAllDevices.Rows.Count == 0)
            {
                return;
            }
            var dtCOVIs = dtAllDevices.Select("TypeID='COVI'");
            foreach (var item in dtCOVIs.AsParallel())
            {
                COVI covi = new COVI();
                /*
                covi.Parent = mainRoadPic;
                covi.DeviceId = item["DeviceID"].ToString();
                covi.Name = item["Name"].ToString();
                covi.TypeId = item["TypeID"].ToString();
                covi.DevicePos = item["DevicePos"].ToString();
                covi.PicX = Convert.ToInt32(item["PicX"].ToString());
                covi.PicY = Convert.ToInt32(item["PicY"].ToString());
                covi.Location = new Point(covi.PicX, covi.PicY);
                if (!string.IsNullOrEmpty(item["Protocol"].ToString()))
                {
                    covi.Protocol = item["Protocol"].ToString();
                }
                */
                InitDevice<COVI>(ref covi, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                COVIs.Add(covi);
            }

            var dtWinds = dtAllDevices.Select("TypeID='Wind'");
            foreach(var item in dtWinds.AsParallel())
            {
                Wind wind = new Wind();
                InitDevice<Wind>(ref wind, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
            }

            var dtFas = dtAllDevices.Select("TypeID='FAN'");
            foreach (var item in dtFas.AsParallel())
            {
                Fan fan = new Fan();
                InitDevice<Fan>(ref fan, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                FANs.Add(fan);
            }

            var dtTSs = dtAllDevices.Select("TypeID='TS'");
            foreach (var item in dtTSs.AsParallel())
            {
                TS ts = new TS();
                InitDevice<TS>(ref ts, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                TSs.Add(ts);
            }

            var dtLamps = dtAllDevices.Select("DevicePos='Light'");
            foreach (var item in dtLamps.AsParallel())
            {
                Lamp lamp = new Lamp();
                InitDevice<Lamp>(ref lamp, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                Lamps.Add(lamp);
            }

            var dtFcms = dtAllDevices.Select("TypeID='FCMS'");
            foreach (var item in dtFcms.AsParallel())
            {
                FCMS fcms = new FCMS();
                InitDevice<FCMS>(ref fcms, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                FCMSs.Add(fcms);
            }

            var dtFiberPoint = dtAllDevices.Select("TypeID='Fiber'");
            foreach (var item in dtFiberPoint.AsParallel())
            {
                FiberPoint fiberPoint = new FiberPoint();
                InitDevice<FiberPoint>(ref fiberPoint, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                FiberPoints.Add(fiberPoint);
            }

            var dtFD = dtAllDevices.Select("TypeID='FD'");
            foreach (var item in dtFD.AsParallel())
            {
                FD fd = new FD();
                InitDevice<FD>(ref fd, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                FDs.Add(fd);
            }

            var dtSmoke = dtAllDevices.Select("TypeID='Somke'");
            foreach (var item in dtSmoke.AsParallel())
            {
                Smoke smoke = new Smoke();
                InitDevice<Smoke>(ref smoke, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                Smokes.Add(smoke);
            }

            var dtPLC = dtAllDevices.Select("TypeID='LC'");
            foreach (var item in dtPLC.AsParallel())
            {
                LC lc = new LC();
                Global.PlcStatus.Add(item["DeviceID"].ToString(), true);
                InitDevice<LC>(ref lc, item["DeviceID"].ToString(), item["Name"].ToString(), item["TypeID"].ToString(), item["DevicePos"].ToString(), item["PicX"].ToString(), item["PicY"].ToString(), item["Protocol"].ToString());
                LCs.Add(lc);
            }
        }
        /// <summary>
        /// 初始化设备赋值
        /// </summary>
        /// <typeparam name="TDeviceType">设备对象类型</typeparam>
        /// <param name="device">设备对象</param>
        /// <param name="deviceId">设备ID</param>
        /// <param name="deviceName">设备名称</param>
        /// <param name="typeId">类型ID</param>
        /// <param name="devicePos">桩号</param>
        /// <param name="picX">x位置</param>
        /// <param name="picY">y位置</param>
        /// <param name="protocol">使用协议</param>
        private void InitDevice<TDeviceType>(ref TDeviceType device, string deviceId, string deviceName, string typeId, string devicePos, string picX, string picY, string protocol) where TDeviceType : DeviceBase, new()
        {
            device.Parent = mainRoadPic;
            device.DeviceId = deviceId;
            device.Name = deviceName;
            device.TypeId = typeId;
            device.DevicePos = devicePos;
            device.PicX = Convert.ToInt32(picX);
            device.PicY = Convert.ToInt32(picY);
            device.Location = new Point(device.PicX, device.PicY);
            if (!string.IsNullOrEmpty(protocol))
            {
                device.Protocol = protocol;
            }
        }
        /// <summary>
        /// 定期从数据库中刷新设备状态，此方法周期较长，并非用作实时状态维护
        /// </summary>
        private async void RefreshDeviceStatus()
        {
            DBHelper dh = new DBHelper();
            DataTable dtStatus = await dh.GetTableAsync("SELECT M_Device.DeviceID, M_DevicesStatus.StatusID, M_DevicesStatus.StatusDescription, M_Device.UpdateTime FROM M_Device LEFT OUTER JOIN  M_DevicesStatus ON M_Device.DeviceStatusID = M_DevicesStatus.StatusID");

            foreach (Control deviceControl in this.mainRoadPic.Controls.AsParallel())
            {
                if (deviceControl is DeviceBase device)
                {
                    DataRow dr = dtStatus.Select("DeviceID='" + device.DeviceId + "'")[0];
                    if (dr["StatusID"].ToString() != string.Empty)
                    {
                        device.DeviceStatusId = dr["StatusID"].ToString();
                    }
                    if (dr["StatusDescription"].ToString() != string.Empty)
                    {
                        device.StatusDescription = dr["StatusDescription"].ToString();
                    }
                    if (dr["UpdateTime"].ToString() != string.Empty)
                    {
                        device.UpdateTime = Convert.ToDateTime(dr["UpdateTime"].ToString());
                    }
                }
            }
        }
        /// <summary>
        /// 退出程序
        /// </summary>
        private void AppExit()
        {
            DialogResult dialogResult = MessageBox.Show("您确定要退出本监控程序么？", "退出确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
            if (dialogResult == DialogResult.Yes)
            {
                try
                {
                    FanTimeControl.SaveLastTime();
                    ReciveStateServiceHost.Close();
                    Application.Exit();
                }
                catch
                {
                    MessageBox.Show("程序退出失败，请重试", "程序退出异常", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }
        }

        private void appExitPic_Click(object sender, EventArgs e)
        {
            AppExit();
        }

        private void timerRefreshStatus_Tick(object sender, EventArgs e)
        {
            RefreshDeviceStatus();
        }

        private void BtPlan_Click(object sender, EventArgs e)
        {
            PlanForm f = new PlanForm();
            f.StartPosition = FormStartPosition.CenterScreen;
            f.ShowDialog();
        }

        private void BtTimePlan_Click(object sender, EventArgs e)
        {
            PlanTime f = new PlanTime();
            f.StartPosition = FormStartPosition.CenterScreen;
            f.ShowDialog();
        }

        private void MinisizeForm_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void BtAlarm_Click(object sender, EventArgs e)
        {
            AlarmForm f = new AlarmForm();
            f.StartPosition = FormStartPosition.CenterScreen;
            f.ShowDialog();
        }
    }
}
